package com.loong.android.tools;

import static android.app.Activity.RESULT_OK;

import android.app.Activity;
import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.StatFs;
import android.provider.MediaStore;
import android.text.TextUtils;

import androidx.annotation.Nullable;
import androidx.core.content.FileProvider;

import com.loong.android.LonApp;
import com.loong.android.LonWin;
import com.loong.android.WinLife;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;

/**
 * 文件操作，注意多数函数需要先获取文件读取和写入的权限( READ_EXTERNAL_STORAGE 和 WRITE_EXTERNAL_STORAGE )
 */
public class LonFile extends File {
    private final static int KB = 1024;

    //文件目录类型-系统提醒铃声
    public final static String DIRECTORY_ALARMS = Environment.DIRECTORY_ALARMS;
    //文件目录类型-DCIM
    public final static String DIRECTORY_DCIM = Environment.DIRECTORY_DCIM;
    //文件目录类型-下载
    public final static String DIRECTORY_DOWNLOADS = Environment.DIRECTORY_DOWNLOADS;
    //文件目录类型-电影
    public final static String DIRECTORY_MOVIES = Environment.DIRECTORY_MOVIES;
    //文件目录类型-音乐
    public final static String DIRECTORY_MUSIC = Environment.DIRECTORY_MUSIC;
    //文件目录类型-系统通知铃声
    public final static String DIRECTORY_NOTIFICATIONS = Environment.DIRECTORY_NOTIFICATIONS;
    //文件目录类型-图片
    public final static String DIRECTORY_PICTURES = Environment.DIRECTORY_PICTURES;
    //文件目录类型-系统广播
    public final static String DIRECTORY_PODCASTS = Environment.DIRECTORY_PODCASTS;
    //文件目录类型-系统铃声
    public final static String DIRECTORY_RINGTONES = Environment.DIRECTORY_RINGTONES;

    public LonFile(File file) {
        super(file.getAbsolutePath());
    }

    public LonFile(URI uri) {
        super(uri);
    }

    /**
     * @param parent 父目录文件对象
     * @param child 文件名称
     */
    public LonFile(File parent, String child) {
        super(parent, child);
    }

    /**
     * @param parent 父目录路径
     * @param child 文件名称
     */
    public LonFile(String parent, String child) {
        super(parent, child);
    }

    /**
     * @param path 文件或目录的路径
     */
    public LonFile(String path) {
        super(path);
    }

    /**
     * 判断文件或目录是否存在
     */
    public boolean exists() {
        return super.exists();
    }

    /**
     * 获取父目录的绝对路径
     */
    public String getParent() {
        return super.getParent();
    }

    /**
     * 获取父目录Lon文件对象
     */
    public LonFile getParentLonFile() {
        File file = super.getParentFile();
        if(file == null) return null;
        return new LonFile(file);
    }

    /**
     * 获取最后修改时间戳，单位为ms
     */
    public long lastModified() {
        return super.lastModified();
    }

    /**
     * 删除文件。如果是目录，必须为空目录才能被删除，否则删除失败。
     * 若希望删除目录及其所有子目录和文件，可以使用{@link LonFile#deleteDir}函数；
     * 若只想删除目录的所有子目录和文件，保留目录本身，使用{@link LonFile#clearDir}函数;
     */
    public boolean delete() {
        return super.delete();
    }

    /**
     * 当文件存在时删除文件。如果是目录，必须为空目录才能被删除，否则删除失败。
     */
    public void deleteOnExit() {
        super.deleteOnExit();
    }

    /**
     * 判断是否为文件
     */
    public boolean isFile() {
        return super.isFile();
    }

    /**
     * 判断是否为目录
     */
    public boolean isDir() {
        return super.isDirectory();
    }

    /**
     * 取文件的长度
     */
    public long length() {
        return super.length();
    }

    /**
     * 取得文件对象构建的路径。若当前文件对象是使用相对路径创建的，那么就得到相对路径；
     * 若使用绝对路径创建，那么就得到绝对路径。
     */
    public String getPath() {
        return super.getPath();
    }

    /**
     * 取文件的绝对路径。getPath和getAbsolutePath的区别:
     * 假如当前目录是: a/b/
     * 使用相对路径构建文件对象: new File("../c/d.txt");
     * getPath得到 ../c/d.txt;
     * getAbsolutePath得到 a/b/../c/d.txt;
     */
    public String getAbsolutePath() {
        return super.getAbsolutePath();
    }

    /**
     * 取得规范的绝对路径。getCanonicalPath和getAbsolutePath的区别:
     * 假如当前目录是: a/b/
     * 使用相对路径构建文件对象: new File("../c/d.txt");
     * getCanonicalPath得到 a/b/c/d.txt;
     * getAbsolutePath得到 a/b/../c/d.txt;
     */
    public String getCanonicalPath() {
        try {
            return super.getCanonicalPath();
        } catch (IOException ignore) {
            return null;
        }
    }

    /**
     * 创建目录。注意确保待创建目录的父目录是存在的，否则目标目录无法成功创建。
     * 若希望自动创建不存在的父目录，请使用{@link LonFile#mkdirs}函数.
     */
    public boolean mkdir() {
        return super.mkdir();
    }

    /**
     * 创建目录，若存在未创建的父目录，则自动创建。
     * 假如要创建目录：a/b/c, 而a/b目录不存在，则自动先创建a/b目录，再创建a/b/c目录
     */
    public boolean mkdirs() {
        return super.mkdirs();
    }

    /**
     * 原子地创建一个新的、空白的文件，该文件的名称由这个抽象路径名指定，当且仅当具有该名称的文件还不存在。
     * 对文件存在性的检查以及在文件不存在时创建文件这两个操作是一个单一的操作，并且这个操作相对于所有可能影响该文件的其他文件系统活动是原子性的。
     * 注：此方法不应被用于文件锁定，因为由此产生的协议无法保证可靠工作。相反，应该使用 FileLock 设施。
     */
    public boolean createNewFile() {
        try {
            return super.createNewFile();
        } catch (IOException ignore) {
            return false;
        }
    }

    /**
     * 列举目录的子文件和目录
     *
     * @return 返回子文件和目录的对象数组
     */
    public LonFile[] listLonFiles() {
        File[] files = super.listFiles();
        if (files == null || files.length <= 0) return new LonFile[0];
        LonFile[] output = new LonFile[files.length];
        for (int i = 0; i < files.length; i++) {
            output[i] = new LonFile(files[i]);
        }
        return output;
    }

    /**
     * 复制文件，只能是文件不能是目录，复制目录请使用{@link LonFile#copyDirTo}
     *
     * @param destPath     目标文件路径
     * @param bufferLength 缓冲区尺寸，单位为字节，默认为1024字节，即1KB
     */
    public boolean copyTo(String destPath, int bufferLength) {
        try {
            FileInputStream in = new FileInputStream(super.getAbsolutePath());
            FileOutputStream out = new FileOutputStream(destPath);
            byte[] bytes = new byte[bufferLength];
            int c;
            while ((c = in.read(bytes)) != -1) {
                out.write(bytes, 0, c);
            }
            in.close();
            out.flush();
            out.close();
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    /**
     * 复制文件，只能是文件不能是目录，复制目录请使用{@link LonFile#copyDirTo}
     *
     * @param destPath 目标文件路径
     */
    public boolean copyTo(String destPath) {
        return copyTo(destPath, KB);
    }

    /**
     * 复制目录下的所有子目录和文件到指定的目录下。若目标目录不存在则自动创建
     *
     * @param destPath     目标目录路径
     * @param bufferLength 缓冲区尺寸，单位为字节，默认为1024字节，即1KB
     */
    public boolean copyDirTo(String destPath, int bufferLength) {
        if (destPath == null || destPath.length() <= 0) return false;
        File file = new File(destPath);
        return FileUtils.copyDir(this, file, bufferLength);
    }

    /**
     * 复制目录下的所有子目录和文件到指定的目录下。若目标目录不存在则自动创建
     *
     * @param destPath 目标目录路径
     */
    public boolean copyDirTo(String destPath) {
        if (destPath == null || destPath.length() <= 0) return false;
        File file = new File(destPath);
        return copyDirTo(destPath, KB);
    }

    /**
     * 重命名/移动文件或目录
     *
     * @param destPath 目标文件地址
     */
    public boolean rename(String destPath) {
        File destFile = new File(destPath);
        return super.renameTo(destFile);
    }

    /**
     * 重命名/移动文件或目录
     *
     * @param file 新的文件对象
     */
    public boolean rename(File file) {
        return super.renameTo(file);
    }
    /**
     * 取文件拓展名，不带点号
     */
    public String getExtentName() {
        String path = super.getAbsolutePath();
        return path.substring(path.lastIndexOf(".") + 1);
    }

    /**
     * 递归删除目录以及目录下的所有子目录和文件
     *
     * @param path       目录路径
     * @param deleteSelf 是否删除自身
     */
    private static boolean deleteAllLoop(String path, boolean deleteSelf) {
        File file = new File(path);
        if (!file.exists()) return false;
        if (!file.isDirectory()) return false;
        File[] files = file.listFiles();
        if (files != null) {
            for (File child : files) {
                if (child.isDirectory()) {
                    deleteAllLoop(child.getAbsolutePath(), true);
                } else {
                    child.delete();
                }
            }
        }
        return !deleteSelf || file.delete();
    }

    /**
     * 清空内部缓存目录：data/data/com.xxx.xxx/cache
     *
     * @param context 上下文
     */
    public static boolean clearCacheDir(Context context) {
        if (context == null) return false;
        return deleteAllLoop(context.getCacheDir().getAbsolutePath(), false);
    }

    /**
     * 清空内部的文件目录: data/data/com.xxx.xxx/files
     *
     * @param context 上下文
     */
    public static boolean clearFilesDir(Context context) {
        if (context == null) return false;
        return deleteAllLoop(context.getFilesDir().getAbsolutePath(), false);
    }

    /**
     * 清空内部的数据库目录: data/data/com.xxx.xxx/databases
     *
     * @param context 上下文
     */
    public static boolean clearDatabasesDir(Context context) {
        if (context == null) return false;
        return deleteAllLoop(context.getFilesDir().getParent() + File.separator + "databases", false);
    }

    /**
     * 按名称删除某个数据库
     *
     * @param context 上下文
     * @param dbName  数据库名称
     */
    public static boolean deleteDatabaseByName(Context context, String dbName) {
        if (context == null || dbName == null || dbName.length() <= 0) return false;
        return context.deleteDatabase(dbName);
    }

    /**
     * 清空外部的缓存目录，一般为: storage/emulated/0/android/data/com.xxx.xxx/cache
     *
     * @param context 上下文
     */
    public static boolean clearExternalCacheDir(Context context) {
        if (context == null) return false;
        return deleteAllLoop(context.getExternalCacheDir().getAbsolutePath(), false);
    }

    /**
     * 取外部文件目录
     *
     * @param context 上下文
     * @param type    目录类型：DIRECTORY_ALARMS: 系统提醒铃声；DIRECTORY_MOVIES：电影；DIRECTORY_MUSIC：音乐：
     *                DIRECTORY_NOTIFICATIONS：系统通知铃声；DIRECTORY_PICTURES：图片；DIRECTORY_PODCASTS：系统广播；
     *                DIRECTORY_RINGTONES：系统铃声
     * @return 返回文件对象
     */
    public static LonFile getExternalFilesDir(Context context, String type) {
        if (context == null) return null;
        File file = context.getExternalFilesDir(type);
        if (file == null) return null;
        return new LonFile(file);
    }

    /**
     * 取外部存储卡公开的目录
     *
     * @param type 目录类型：DIRECTORY_ALARMS: 系统提醒铃声；DIRECTORY_DCIM：DCIM；DIRECTORY_DOWNLOADS：下载；
     *             DIRECTORY_MOVIES：电影；DIRECTORY_MUSIC：音乐：DIRECTORY_NOTIFICATIONS：
     *             系统通知铃声；DIRECTORY_PICTURES：图片；DIRECTORY_PODCASTS：系统广播；
     *             DIRECTORY_RINGTONES：系统铃声
     * @return 返回文件对象
     */
    public static LonFile getExternalStoragePublicDir(String type) {
        File file = Environment.getExternalStoragePublicDirectory(type);
        if (file == null) return null;
        return new LonFile(file);
    }

    /**
     * 取目录大小
     *
     * @param file 目录文件对象
     */
    public static long getDirSize(File file) {
        StatFs stat = new StatFs(file.getAbsolutePath());
        long blockSize, availableBlocks;
        if (Build.VERSION.SDK_INT >= 18) {
            blockSize = stat.getBlockSizeLong();
            availableBlocks = stat.getAvailableBlocksLong();
        } else {
            blockSize = stat.getBlockSize();
            availableBlocks = stat.getAvailableBlocks();
        }
        return availableBlocks * blockSize;
    }

    /**
     * 取得文件或目录的大小 如果是目录，会递归获取所有文件及子目录的尺寸，可能耗时比较长
     *
     * @param file 文件对象
     */
    public static long calcFileSize(File file) {
        if (!file.exists()) return 0;
        if (file.isDirectory()) {
            File[] children = file.listFiles();
            long size = 0;
            if (children != null) {
                for (File tmp : children) {
                    size += calcFileSize(new LonFile(tmp));
                }
            }
            return size;
        } else {
            return file.length();
        }
    }


    /**
     * 删除目录自身，及以下的所有文件，包括子目录。
     */
    public static boolean deleteDir(File file) {
        if (file == null || !file.isDirectory()) return false;
        return deleteAllLoop(file.getAbsolutePath(), true);
    }

    /**
     * 删除目录自身，及以下的所有文件，包括子目录。
     */
    public static boolean deleteDir(String dirPath) {
        if (dirPath == null || dirPath.length() <= 0) return false;
        return deleteAllLoop(dirPath, true);
    }

    public static boolean clearDir(File file) {
        if (file == null || !file.isDirectory()) return false;
        return deleteAllLoop(file.getAbsolutePath(), false);
    }

    public static boolean clearDir(String dirPath) {
        if (dirPath == null || dirPath.length() <= 0) return false;
        return deleteAllLoop(dirPath, false);
    }

    /**
     * 调用系统软件打开指定MIME类型的文件。注意需要先获得文件读取和写出权限(READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE)
     *
     * @param context  上下文
     * @param filePath 文件路径
     * @param mimeType 文件mime类型
     */
    public static void openFile(Context context, String filePath, String mimeType) {
        if (context == null) return;
        if (filePath == null || filePath.length() <= 0) return;
        if (mimeType == null || mimeType.length() <= 0) return;
        File file = new File(filePath);
        if (!file.exists()) return;
        Intent intent = new Intent();
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        //设置intent的Action属性
        intent.setAction(Intent.ACTION_VIEW);
        Uri uri = null;
        if (Build.VERSION.SDK_INT >= 24) {
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//注意必须加上这句
            uri = FileProvider.getUriForFile(context, LonApp.getFileAuthority(), file);
        } else {
            uri = Uri.fromFile(file);
        }
        if (uri == null) return;
        //设置intent的data和Type属性。
        intent.setDataAndType(uri, mimeType);
        //跳转
        context.startActivity(intent);
    }

    /**
     * 调用系统软件打开大部分常见后缀名的文件。注意需要先获得文件读取和写出权限(READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE)
     *
     * @param context  上下文
     * @param filePath 文件地址
     */
    public static void openFile(Context context, String filePath) {
        openFile(context, filePath, getMimeType(filePath));
    }

    /**
     * 写按指定编码写出文本内容到文件中。
     * 注意需要先获得文件读取和写出权限(READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE)
     *
     * @param path    写出的文件路径
     * @param content 文本内容
     * @param charset 编码，如：utf-8，gbk等，默认为utf-8
     * @param append  是否在已存在的文本文件尾部添加内容，默认为false，覆盖
     */
    public static void writeText(String path, String content, String charset, boolean append) {
        if (path == null || path.length() <= 0) return;
        if (charset == null || charset.length() <= 0) charset = "utf-8";
        FileUtils.saveFileByCustomCharset(path, content, charset, append);
    }

    /**
     * 以utf-8的编码写出文本内容到文件中。
     *
     * @param path    写出的文件路径
     * @param content 文本内容
     * @param append  是否在已存在的文本文件尾部添加内容，默认为false，覆盖
     */
    public static void writeText(String path, String content, boolean append) {
        writeText(path, content, "utf-8", append);
    }

    /**
     * 以utf-8的编码写出文本内容到文件中。若文件已存在，则覆盖写出。
     *
     * @param path    写出的文件路径
     * @param content 文本内容
     */
    public static void writeText(String path, String content) {
        writeText(path, content, "utf-8", false);
    }

    /**
     * 按指定编码读取文本文件
     * 注意需要先获得文件读取权限(READ_EXTERNAL_STORAGE)
     *
     * @param path    文件路径
     * @param charset 编码，如：utf-8，gbk等，默认为utf-8
     * @return 返回文本文件的内容
     */
    public static String readText(String path, String charset) {
        if (path == null || path.length() <= 0) return null;
        if (charset == null || charset.length() <= 0) charset = "utf-8";
        return FileUtils.getFileByCustomCharset(path, charset);
    }

    /**
     * 按utf-8编码读取文本文件
     *
     * @param path 文件路径
     * @return 返回文本文件的内容
     */
    public static String readText(String path) {
        return readText(path, "utf-8");
    }

    /**
     * 取文件编码，可读取以下几种类型：UTF-8、Unicode、UTF-16BE、GBK
     *
     * @param filePath 文件路径
     */
    public static String getFileCharset(String filePath) {
        if (filePath == null || filePath.length() <= 0) return null;
        return FileUtils.getFileCharsetSimple(new File(filePath));
    }

    /**
     * 读取文件为字节数组
     *
     * @param filePath     文件路径
     * @param bufferLength buffer长度可影响文件读写的速度，默认为1024
     */
    public static byte[] readToBytes(String filePath, int bufferLength) {
        return FileUtils.file2Bytes(filePath, bufferLength);
    }

    /**
     * 读取文件为字节数组
     *
     * @param filePath 文件路径
     */
    public static byte[] readToBytes(String filePath) {
        return FileUtils.file2Bytes(filePath, KB);
    }

    /**
     * 将字节数组写入文件
     *
     * @param filePath 文件路径
     * @param bytes    字节数组
     */
    public static boolean writeBytes(String filePath, byte[] bytes) {
        return FileUtils.bytes2File(bytes, filePath);
    }

    /**
     * 资源文件转字节数组
     *
     * @param context      上下文
     * @param resId        资源id
     * @param bufferLength buffer长度可影响文件读写的速度，默认为1024
     */
    public static byte[] resourceFile2Bytes(Context context, int resId, int bufferLength) {
        return FileUtils.resource2Bytes(context, resId, bufferLength);
    }

    /**
     * 资源文件转字节数组
     *
     * @param context 上下文
     * @param resId   资源id
     */
    public static byte[] resource2Bytes(Context context, int resId) {
        return resourceFile2Bytes(context, resId, KB);
    }

    /**
     * 取内部缓存目录
     *
     * @param context 上下文
     * @return 文件对象
     */
    public static LonFile getCacheDir(Context context) {
        if (context == null) return null;
        File file = context.getCacheDir();
        if (file == null) return null;
        return new LonFile(file);
    }

    /**
     * 取内部文件目录
     *
     * @param context 上下文
     * @return 文件对象
     */
    public static LonFile getFileDir(Context context) {
        if (context == null) return null;
        File file = context.getFilesDir();
        if (file == null) return null;
        return new LonFile(file);
    }

    /**
     * 取内部数据库路径
     *
     * @param context 上下文
     */
    public String getDatabasesPath(Context context) {
        if (context == null) return null;
        return context.getFilesDir().getAbsolutePath() + File.separator + "databases";
    }

    /**
     * 取常见文件的mime类型
     *
     * @param filePath 文件路径
     */
    public static String getMimeType(String filePath) {
        String type = "*/*";
        String end = filePath.substring(filePath.lastIndexOf(".") + 1).toLowerCase();
        if (end.equals("")) return type;
        //在MIME和文件类型的匹配表中找到对应的MIME类型。
        for (String[] map : MIME_MAP) {
            if (end.equals(map[0])) {
                type = map[1];
                break;
            }
        }
        return type;
    }

    public static String handlePickFileUri(Context context, Uri uri) {
        if(uri == null) return null;
        String[] filePathColumn = {MediaStore.Images.Media.DATA};
        String outputPath = null;
        if (!TextUtils.isEmpty(uri.getAuthority())) {
            // 获取选择照片的数据视图
            Cursor cursor = context.getContentResolver().query(uri,
                    filePathColumn, null, null, null);
            if (cursor != null) {
                cursor.moveToFirst();
                // 从数据视图中获取已选择图片的路径
                int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
                outputPath = cursor.getString(columnIndex);
                cursor.close();
            }
        } else {
            outputPath = uri.getPath();
        }
        return outputPath;
    }

    /**
     * 选择文件
     *
     * @param context       上下文
     * @param pickMethod       选择文件的方式，参考PickMethod内部类，默认为PickMethod.PICK
     * @param title       选择器的标题
     * @param mimeType      文件的mime类型，如图片："image/*"
     * @param allowMultiple 是否允许选择多文件，安卓4.3(api18)及以上的版本才有效
     */
    public static void pickFile(Context context, String pickMethod, String title, String mimeType, boolean allowMultiple, PickFileEvent event) {
        Intent intent = new Intent(pickMethod);
        intent.setType(mimeType);
        if (allowMultiple && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
            intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
        }
        final Activity activity = (Activity) context;
        activity.startActivityForResult(Intent.createChooser(intent, title), 0);
        if (activity instanceof LonWin) {
            final String listenerName = LonFile.class.getCanonicalName() + "pickFile" + System.currentTimeMillis();
            ((LonWin) activity).addWinLifeListener(listenerName, new WinLife() {
                @Override
                public void onActivityResult(int requestCode, int resultCode, @Nullable Intent intent) {
                    super.onActivityResult(requestCode, resultCode, intent);
                    if (requestCode != 0) return;
                    ((LonWin) activity).removeWinLifeListener(listenerName);
                    List<String> pickPathList = new ArrayList<>();
                    String pickPath = null;
                    boolean res = false;
                    if (resultCode == RESULT_OK && intent != null) {
                        if(!allowMultiple) {
                            //单选
                            if((pickPath = handlePickFileUri(activity, intent.getData())) != null) {
                                pickPathList.add(pickPath);
                                res = true;
                            }
                        }
                        else {
                            ClipData clipData = intent.getClipData();
                            if(clipData != null && clipData.getItemCount() > 0) {
                                for (int i = 0; i < clipData.getItemCount(); i++) {
                                    ClipData.Item item = clipData.getItemAt(i);
                                    if((pickPath = handlePickFileUri(activity, item.getUri())) != null) {
                                        pickPathList.add(pickPath);
                                        res = true;
                                    }
                                }
                            }
                        }
                    }
                    if (event != null) event.onComplete(res, pickPathList.toArray(new String[0]));
                }
            });
        }
    }

    /**
     * 选择文件
     *
     * @param context       上下文
     * @param title       选择器的标题
     * @param mimeType      文件的mime类型，如图片："image/*"
     * @param allowMultiple 是否允许选择多文件，安卓4.3(api18)及以上的版本才有效
     */
    public static void pickFile(Context context, String title, String mimeType, boolean allowMultiple, PickFileEvent event) {
        pickFile(context, PickMethod.PICK, title, mimeType, allowMultiple, event);
    }

    /**
     * 选择文件
     *
     * @param context       上下文
     * @param mimeType      文件的mime类型，如图片："image/*"
     * @param allowMultiple 是否允许选择多文件，安卓4.3(api18)及以上的版本才有效
     */
    public static void pickFile(Context context, String mimeType, boolean allowMultiple, PickFileEvent event) {
        pickFile(context, PickMethod.PICK, "选择文件", mimeType, allowMultiple, event);
    }

    /**
     * 选择文件的接口事件
     */
    public abstract static class PickFileEvent {
        /**
         * 文件选择完毕
         *
         * @param result   结果
         * @param filePath 选取的文件路径
         */
        public void onComplete(boolean result, String[] filePath) {

        }
    }

    /**
     * 选择文件的方式
     */
    public static class PickMethod {
        public final static String PICK = Intent.ACTION_PICK;
        public final static String GET_CONTENT = Intent.ACTION_GET_CONTENT;
        public final static String OPEN_DOCUMENT = "android.intent.action.OPEN_DOCUMENT";
    }

    private static final String[][] MIME_MAP = {
            //{后缀名，MIME类型}
            {"3gp", "video/3gpp"},
            {"aab", "application/x-authoware-bin"},
            {"aam", "application/x-authoware-map"},
            {"aas", "application/x-authoware-seg"},
            {"ai", "application/postscript"},
            {"aif", "audio/x-aiff"},
            {"aifc", "audio/x-aiff"},
            {"aiff", "audio/x-aiff"},
            {"als", "audio/X-Alpha5"},
            {"amc", "application/x-mpeg"},
            {"ani", "application/octet-stream"},
            {"apk", "application/vnd.android.package-archive"},
            {"asc", "text/plain"},
            {"asd", "application/astound"},
            {"asf", "video/x-ms-asf"},
            {"asn", "application/astound"},
            {"asp", "application/x-asap"},
            {"asx", "video/x-ms-asf"},
            {"au", "audio/basic"},
            {"avb", "application/octet-stream"},
            {"avi", "video/x-msvideo"},
            {"awb", "audio/amr-wb"},
            {"bcpio", "application/x-bcpio"},
            {"bin", "application/octet-stream"},
            {"bld", "application/bld"},
            {"bld2", "application/bld2"},
            {"bmp", "image/bmp"},
            {"bpk", "application/octet-stream"},
            {"bz2", "application/x-bzip2"},
            {"c", "text/plain"},
            {"cal", "image/x-cals"},
            {"ccn", "application/x-cnc"},
            {"cco", "application/x-cocoa"},
            {"cdf", "application/x-netcdf"},
            {"cgi", "magnus-internal/cgi"},
            {"chat", "application/x-chat"},
            {"class", "application/octet-stream"},
            {"clp", "application/x-msclip"},
            {"cmx", "application/x-cmx"},
            {"co", "application/x-cult3d-object"},
            {"cod", "image/cis-cod"},
            {"conf", "text/plain"},
            {"cpio", "application/x-cpio"},
            {"cpp", "text/plain"},
            {"cpt", "application/mac-compactpro"},
            {"crd", "application/x-mscardfile"},
            {"csh", "application/x-csh"},
            {"csm", "chemical/x-csml"},
            {"csml", "chemical/x-csml"},
            {"css", "text/css"},
            {"cur", "application/octet-stream"},
            {"dcm", "x-lml/x-evm"},
            {"dcr", "application/x-director"},
            {"dcx", "image/x-dcx"},
            {"dhtml", "text/html"},
            {"dir", "application/x-director"},
            {"dll", "application/octet-stream"},
            {"dmg", "application/octet-stream"},
            {"dms", "application/octet-stream"},
            {"doc", "application/msword"},
            {"docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
            {"dot", "application/x-dot"},
            {"dvi", "application/x-dvi"},
            {"dwf", "drawing/x-dwf"},
            {"dwg", "application/x-autocad"},
            {"dxf", "application/x-autocad"},
            {"dxr", "application/x-director"},
            {"ebk", "application/x-expandedbook"},
            {"emb", "chemical/x-embl-dl-nucleotide"},
            {"embl", "chemical/x-embl-dl-nucleotide"},
            {"eps", "application/postscript"},
            {"eri", "image/x-eri"},
            {"es", "audio/echospeech"},
            {"esl", "audio/echospeech"},
            {"etc", "application/x-earthtime"},
            {"etx", "text/x-setext"},
            {"evm", "x-lml/x-evm"},
            {"evy", "application/x-envoy"},
            {"exe", "application/octet-stream"},
            {"fh4", "image/x-freehand"},
            {"fh5", "image/x-freehand"},
            {"fhc", "image/x-freehand"},
            {"fif", "image/fif"},
            {"fm", "application/x-maker"},
            {"fpx", "image/x-fpx"},
            {"fvi", "video/isivideo"},
            {"gau", "chemical/x-gaussian-input"},
            {"gca", "application/x-gca-compressed"},
            {"gdb", "x-lml/x-gdb"},
            {"gif", "image/gif"},
            {"gps", "application/x-gps"},
            {"gtar", "application/x-gtar"},
            {"gz", "application/x-gzip"},
            {"h", "text/plain"},
            {"hdf", "application/x-hdf"},
            {"hdm", "text/x-hdml"},
            {"hdml", "text/x-hdml"},
            {"hlp", "application/winhlp"},
            {"hqx", "application/mac-binhex40"},
            {"htm", "text/html"},
            {"html", "text/html"},
            {"hts", "text/html"},
            {"ice", "x-conference/x-cooltalk"},
            {"ico", "application/octet-stream"},
            {"ief", "image/ief"},
            {"ifm", "image/gif"},
            {"ifs", "image/ifs"},
            {"imy", "audio/melody"},
            {"ins", "application/x-NET-Install"},
            {"ips", "application/x-ipscript"},
            {"ipx", "application/x-ipix"},
            {"it", "audio/x-mod"},
            {"itz", "audio/x-mod"},
            {"ivr", "i-world/i-vrml"},
            {"j2k", "image/j2k"},
            {"jad", "text/vnd.sun.j2me.app-descriptor"},
            {"jam", "application/x-jam"},
            {"jar", "application/java-archive"},
            {"java", "text/plain"},
            {"jnlp", "application/x-java-jnlp-file"},
            {"jpe", "image/jpeg"},
            {"jpeg", "image/jpeg"},
            {"jpg", "image/jpeg"},
            {"jpz", "image/jpeg"},
            {"js", "application/x-javascript"},
            {"jwc", "application/jwc"},
            {"kjx", "application/x-kjx"},
            {"lak", "x-lml/x-lak"},
            {"latex", "application/x-latex"},
            {"lcc", "application/fastman"},
            {"lcl", "application/x-digitalloca"},
            {"lcr", "application/x-digitalloca"},
            {"lgh", "application/lgh"},
            {"lha", "application/octet-stream"},
            {"lml", "x-lml/x-lml"},
            {"lmlpack", "x-lml/x-lmlpack"},
            {"log", "text/plain"},
            {"lsf", "video/x-ms-asf"},
            {"lsx", "video/x-ms-asf"},
            {"lzh", "application/x-lzh"},
            {"m13", "application/x-msmediaview"},
            {"m14", "application/x-msmediaview"},
            {"m15", "audio/x-mod"},
            {"m3u", "audio/x-mpegurl"},
            {"m3url", "audio/x-mpegurl"},
            {"m4a", "audio/mp4a-latm"},
            {"m4b", "audio/mp4a-latm"},
            {"m4p", "audio/mp4a-latm"},
            {"m4u", "video/vnd.mpegurl"},
            {"m4v", "video/x-m4v"},
            {"ma1", "audio/ma1"},
            {"ma2", "audio/ma2"},
            {"ma3", "audio/ma3"},
            {"ma5", "audio/ma5"},
            {"man", "application/x-troff-man"},
            {"map", "magnus-internal/imagemap"},
            {"mbd", "application/mbedlet"},
            {"mct", "application/x-mascot"},
            {"mdb", "application/x-msaccess"},
            {"mdz", "audio/x-mod"},
            {"me", "application/x-troff-me"},
            {"mel", "text/x-vmel"},
            {"mi", "application/x-mif"},
            {"mid", "audio/midi"},
            {"midi", "audio/midi"},
            {"mif", "application/x-mif"},
            {"mil", "image/x-cals"},
            {"mio", "audio/x-mio"},
            {"mmf", "application/x-skt-lbs"},
            {"mng", "video/x-mng"},
            {"mny", "application/x-msmoney"},
            {"moc", "application/x-mocha"},
            {"mocha", "application/x-mocha"},
            {"mod", "audio/x-mod"},
            {"mof", "application/x-yumekara"},
            {"mol", "chemical/x-mdl-molfile"},
            {"mop", "chemical/x-mopac-input"},
            {"mov", "video/quicktime"},
            {"movie", "video/x-sgi-movie"},
            {"mp2", "audio/x-mpeg"},
            {"mp3", "audio/x-mpeg"},
            {"mp4", "video/mp4"},
            {"mpc", "application/vnd.mpohun.certificate"},
            {"mpe", "video/mpeg"},
            {"mpeg", "video/mpeg"},
            {"mpg", "video/mpeg"},
            {"mpg4", "video/mp4"},
            {"mpga", "audio/mpeg"},
            {"mpn", "application/vnd.mophun.application"},
            {"mpp", "application/vnd.ms-project"},
            {"mps", "application/x-mapserver"},
            {"mrl", "text/x-mrml"},
            {"mrm", "application/x-mrm"},
            {"ms", "application/x-troff-ms"},
            {"msg", "application/vnd.ms-outlook"},
            {"mts", "application/metastream"},
            {"mtx", "application/metastream"},
            {"mtz", "application/metastream"},
            {"mzv", "application/metastream"},
            {"nar", "application/zip"},
            {"nbmp", "image/nbmp"},
            {"nc", "application/x-netcdf"},
            {"ndb", "x-lml/x-ndb"},
            {"ndwn", "application/ndwn"},
            {"nif", "application/x-nif"},
            {"nmz", "application/x-scream"},
            {"nokia-op-logo", "image/vnd.nok-oplogo-color"},
            {"npx", "application/x-netfpx"},
            {"nsnd", "audio/nsnd"},
            {"nva", "application/x-neva1"},
            {"oda", "application/oda"},
            {"ogg", "audio/ogg"},
            {"oom", "application/x-AtlasMate-Plugin"},
            {"pac", "audio/x-pac"},
            {"pae", "audio/x-epac"},
            {"pan", "application/x-pan"},
            {"pbm", "image/x-portable-bitmap"},
            {"pcx", "image/x-pcx"},
            {"pda", "image/x-pda"},
            {"pdb", "chemical/x-pdb"},
            {"pdf", "application/pdf"},
            {"pfr", "application/font-tdpfr"},
            {"pgm", "image/x-portable-graymap"},
            {"pict", "image/x-pict"},
            {"pm", "application/x-perl"},
            {"pmd", "application/x-pmd"},
            {"png", "image/png"},
            {"pnm", "image/x-portable-anymap"},
            {"pnz", "image/png"},
            {"pot", "application/vnd.ms-powerpoint"},
            {"ppm", "image/x-portable-pixmap"},
            {"pps", "application/vnd.ms-powerpoint"},
            {"ppt", "application/vnd.ms-powerpoint"},
            {"pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"},
            {"pqf", "application/x-cprplayer"},
            {"pqi", "application/cprplayer"},
            {"prc", "application/x-prc"},
            {"prop", "text/plain"},
            {"proxy", "application/x-ns-proxy-autoconfig"},
            {"ps", "application/postscript"},
            {"ptlk", "application/listenup"},
            {"pub", "application/x-mspublisher"},
            {"pvx", "video/x-pv-pvx"},
            {"qcp", "audio/vnd.qcelp"},
            {"qt", "video/quicktime"},
            {"qti", "image/x-quicktime"},
            {"qtif", "image/x-quicktime"},
            {"r3t", "text/vnd.rn-realtext3d"},
            {"ra", "audio/x-pn-realaudio"},
            {"ram", "audio/x-pn-realaudio"},
            {"rar", "application/x-rar-compressed"},
            {"ras", "image/x-cmu-raster"},
            {"rc", "text/plain"},
            {"rdf", "application/rdf+xml"},
            {"rf", "image/vnd.rn-realflash"},
            {"rgb", "image/x-rgb"},
            {"rlf", "application/x-richlink"},
            {"rm", "audio/x-pn-realaudio"},
            {"rmf", "audio/x-rmf"},
            {"rmm", "audio/x-pn-realaudio"},
            {"rmvb", "audio/x-pn-realaudio"},
            {"rnx", "application/vnd.rn-realplayer"},
            {"roff", "application/x-troff"},
            {"rp", "image/vnd.rn-realpix"},
            {"rpm", "audio/x-pn-realaudio-plugin"},
            {"rt", "text/vnd.rn-realtext"},
            {"rte", "x-lml/x-gps"},
            {"rtf", "application/rtf"},
            {"rtg", "application/metastream"},
            {"rtx", "text/richtext"},
            {"rv", "video/vnd.rn-realvideo"},
            {"rwc", "application/x-rogerwilco"},
            {"s3m", "audio/x-mod"},
            {"s3z", "audio/x-mod"},
            {"sca", "application/x-supercard"},
            {"scd", "application/x-msschedule"},
            {"sdf", "application/e-score"},
            {"sea", "application/x-stuffit"},
            {"sgm", "text/x-sgml"},
            {"sgml", "text/x-sgml"},
            {"sh", "application/x-sh"},
            {"shar", "application/x-shar"},
            {"shtml", "magnus-internal/parsed-html"},
            {"shw", "application/presentations"},
            {"si6", "image/si6"},
            {"si7", "image/vnd.stiwap.sis"},
            {"si9", "image/vnd.lgtwap.sis"},
            {"sis", "application/vnd.symbian.install"},
            {"sit", "application/x-stuffit"},
            {"skd", "application/x-Koan"},
            {"skm", "application/x-Koan"},
            {"skp", "application/x-Koan"},
            {"skt", "application/x-Koan"},
            {"slc", "application/x-salsa"},
            {"smd", "audio/x-smd"},
            {"smi", "application/smil"},
            {"smil", "application/smil"},
            {"smp", "application/studiom"},
            {"smz", "audio/x-smd"},
            {"snd", "audio/basic"},
            {"spc", "text/x-speech"},
            {"spl", "application/futuresplash"},
            {"spr", "application/x-sprite"},
            {"sprite", "application/x-sprite"},
            {"spt", "application/x-spt"},
            {"src", "application/x-wais-source"},
            {"stk", "application/hyperstudio"},
            {"stm", "audio/x-mod"},
            {"sv4cpio", "application/x-sv4cpio"},
            {"sv4crc", "application/x-sv4crc"},
            {"svf", "image/vnd"},
            {"svg", "image/svg-xml"},
            {"svh", "image/svh"},
            {"svr", "x-world/x-svr"},
            {"swf", "application/x-shockwave-flash"},
            {"swfl", "application/x-shockwave-flash"},
            {"t", "application/x-troff"},
            {"tad", "application/octet-stream"},
            {"talk", "text/x-speech"},
            {"tar", "application/x-tar"},
            {"taz", "application/x-tar"},
            {"tbp", "application/x-timbuktu"},
            {"tbt", "application/x-timbuktu"},
            {"tcl", "application/x-tcl"},
            {"tex", "application/x-tex"},
            {"texi", "application/x-texinfo"},
            {"texinfo", "application/x-texinfo"},
            {"tgz", "application/x-tar"},
            {"thm", "application/vnd.eri.thm"},
            {"tif", "image/tiff"},
            {"tiff", "image/tiff"},
            {"tki", "application/x-tkined"},
            {"tkined", "application/x-tkined"},
            {"toc", "application/toc"},
            {"toy", "image/toy"},
            {"tr", "application/x-troff"},
            {"trk", "x-lml/x-gps"},
            {"trm", "application/x-msterminal"},
            {"tsi", "audio/tsplayer"},
            {"tsp", "application/dsptype"},
            {"tsv", "text/tab-separated-values"},
            {"tsv", "text/tab-separated-values"},
            {"ttf", "application/octet-stream"},
            {"ttz", "application/t-time"},
            {"txt", "text/plain"},
            {"ult", "audio/x-mod"},
            {"ustar", "application/x-ustar"},
            {"uu", "application/x-uuencode"},
            {"uue", "application/x-uuencode"},
            {"vcd", "application/x-cdlink"},
            {"vcf", "text/x-vcard"},
            {"vdo", "video/vdo"},
            {"vib", "audio/vib"},
            {"viv", "video/vivo"},
            {"vivo", "video/vivo"},
            {"vmd", "application/vocaltec-media-desc"},
            {"vmf", "application/vocaltec-media-file"},
            {"vmi", "application/x-dreamcast-vms-info"},
            {"vms", "application/x-dreamcast-vms"},
            {"vox", "audio/voxware"},
            {"vqe", "audio/x-twinvq-plugin"},
            {"vqf", "audio/x-twinvq"},
            {"vql", "audio/x-twinvq"},
            {"vre", "x-world/x-vream"},
            {"vrml", "x-world/x-vrml"},
            {"vrt", "x-world/x-vrt"},
            {"vrw", "x-world/x-vream"},
            {"vts", "workbook/formulaone"},
            {"wav", "audio/x-wav"},
            {"wax", "audio/x-ms-wax"},
            {"wbmp", "image/vnd.wap.wbmp"},
            {"web", "application/vnd.xara"},
            {"wi", "image/wavelet"},
            {"wis", "application/x-InstallShield"},
            {"wm", "video/x-ms-wm"},
            {"wma", "audio/x-ms-wma"},
            {"wmd", "application/x-ms-wmd"},
            {"wmf", "application/x-msmetafile"},
            {"wml", "text/vnd.wap.wml"},
            {"wmlc", "application/vnd.wap.wmlc"},
            {"wmls", "text/vnd.wap.wmlscript"},
            {"wmlsc", "application/vnd.wap.wmlscriptc"},
            {"wmlscript", "text/vnd.wap.wmlscript"},
            {"wmv", "audio/x-ms-wmv"},
            {"wmx", "video/x-ms-wmx"},
            {"wmz", "application/x-ms-wmz"},
            {"wpng", "image/x-up-wpng"},
            {"wps", "application/vnd.ms-works"},
            {"wpt", "x-lml/x-gps"},
            {"wri", "application/x-mswrite"},
            {"wrl", "x-world/x-vrml"},
            {"wrz", "x-world/x-vrml"},
            {"ws", "text/vnd.wap.wmlscript"},
            {"wsc", "application/vnd.wap.wmlscriptc"},
            {"wv", "video/wavelet"},
            {"wvx", "video/x-ms-wvx"},
            {"wxl", "application/x-wxl"},
            {"x-gzip", "application/x-gzip"},
            {"xar", "application/vnd.xara"},
            {"xbm", "image/x-xbitmap"},
            {"xdm", "application/x-xdma"},
            {"xdma", "application/x-xdma"},
            {"xdw", "application/vnd.fujixerox.docuworks"},
            {"xht", "application/xhtml+xml"},
            {"xhtm", "application/xhtml+xml"},
            {"xhtml", "application/xhtml+xml"},
            {"xla", "application/vnd.ms-excel"},
            {"xlc", "application/vnd.ms-excel"},
            {"xll", "application/x-excel"},
            {"xlm", "application/vnd.ms-excel"},
            {"xls", "application/vnd.ms-excel"},
            {"xlt", "application/vnd.ms-excel"},
            {"xlw", "application/vnd.ms-excel"},
            {"xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
            {"xm", "audio/x-mod"},
            {"xml", "text/xml"},
            {"xmz", "audio/x-mod"},
            {"xpi", "application/x-xpinstall"},
            {"xpm", "image/x-xpixmap"},
            {"xsit", "text/xml"},
            {"xsl", "text/xml"},
            {"xul", "text/xul"},
            {"xwd", "image/x-xwindowdump"},
            {"xyz", "chemical/x-pdb"},
            {"yz1", "application/x-yz1"},
            {"z", "application/x-compress"},
            {"zac", "application/x-zaurus-zac"},
            {"zip", "application/zip"},
            {"", "*/*"}
    };
}
